#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import json
import bnetd


class WrtConst:

    MY_NAME = "bnetd"
    MY_GROUP = "bnetd"

    etcDir = os.path.join("/etc", MY_NAME)
    libDir = os.path.join("/usr", "lib64", MY_NAME)
    libexecDir = os.path.join("/usr", "libexec", MY_NAME)
    dataDir = os.path.join("/usr", "share", MY_NAME)
    tmpDir = os.path.join("/tmp", MY_NAME)
    varDir = os.path.join("/var", MY_NAME)

    procIpForwareFile = "/proc/sys/net/ipv4/ip_forward"


class WrtParam:

    def __init__(self):
        self.LIB_DIR = os.path.join("/usr", "lib64", WrtConst.MY_NAME)
        self.LIB_UPLINK_DIR = os.path.join(self.LIB_DIR, "uplink")
        self.LIB_OBCONN_DIR = os.path.join(self.LIB_DIR, "obconn")

        self.CFG_DIR = os.path.join("/etc", WrtConst.MY_NAME)
        self.CFG_GLOBAL_FILE = os.path.join(self.CFG_DIR, "global.json")
        self.CFG_SETTINGS_FILE = os.path.join(self.CFG_DIR, "settings.json")
        self.CFG_UPLINK_DIR = os.path.join(self.CFG_DIR, "uplink")
        self.CFG_OBCONN_DIR = os.path.join(self.CFG_DIR, "obconn")

        self.CACHE_DIR = os.path.join("/var", "cache", WrtConst.MY_NAME)
        self.CACHE_OBCONN_DIR = os.path.join(self.CACHE_DIR, "obconn")

        self.RUN_DIR = os.path.join("/run", WrtConst.MY_NAME)
        self.RUN_PID_FILE = os.path.join(self.RUN_DIR, "%s.pid" % (WrtConst.MY_NAME))

        self.DATA_DIR = os.path.join("/var", "lib", WrtConst.MY_NAME)
        self.PREFIX_RECORD_FILE = os.path.join(self.DATA_DIR, "prefix.json")

        self.LOG_DIR = os.path.join("/var", "log", WrtConst.MY_NAME)

        self.uuid = None

        self.settings = None

        self.pluginHub = None
        self.prefixPool = None
        self.netIfPool = None
        self.gateway = None

        self.obConnManager = None

        self.mainloop = None

        self.abortOnError = False
        self.logLevel = None
        self.config = None

    def isInGateway(self):
        return (self.uuid is None)


class WrtUserSettings:

    def __init__(self, param):
        self._param = param
        
        self._data = {}
        try:
            with open(self._param.CFG_SETTINGS_FILE) as f:
                self._data = json.load(f)
        except FileNotFoundError:
            pass
        except json.JSONDecodeError:
            raise bnetd.InvalidCfgError(self._param.CFG_SETTINGS_FILE, "invalid format")

        if "obconn" not in self._data:
            self._data["obconn"] = {}
        if "in-gateway" not in self._data["obconn"]:
            self._data["obconn"]["in-gateway"] = []
        if "auto-connect" not in self._data["obconn"]:
            self._data["obconn"]["auto-connect"] = {}

        if "uplink" not in self._data:
            self._data["uplink"] = {}
        if "auto-connect" not in self._data["uplink"]:
            self._data["uplink"]["auto-connect"] = {}

    def save(self):
        with open(self._param.CFG_SETTINGS_FILE, "w") as f:
            json.dump(self._data, f, indent=4)

    def uplink_is_auto_connect(self, uplink):
        if uplink.get_uuid() in self._data["uplink"]["auto-connect"]:
            assert uplink.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
            return self._data["uplink"]["auto-connect"][uplink.get_uuid()]
        else:
            return uplink.is_auto_connect()

    def uplink_set_auto_connect(self, uplink, value):
        assert uplink.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
        self._data["uplink"]["auto-connect"][uplink.get_uuid()] = bool(value)

    def uplink_reset_auto_connect(self, uplink):
        self._data["uplink"]["auto-connect"].pop(uplink.get_uuid(), None)

    def obconn_is_in_gateway(self, obconn):
        if obconn.get_uuid() in self._data["obconn"]["in-gateway"]:
            assert obconn.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
            return True
        else:
            return obconn.is_in_gateway()

    def obconn_set_in_gateway(self, obconn):
        assert obconn.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
        self._data["obconn"]["in-gateway"].append(obconn.get_uuid())

    def obconn_reset_in_gateway(self, obconn):
        self._data["obconn"]["in-gateway"].pop(obconn.get_uuid())

    def obconn_is_auto_connect(self, obconn):
        if obconn.get_uuid() in self._data["obconn"]["auto-connect"]:
            assert obconn.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
            return self._data["obconn"]["auto-connect"][obconn.get_uuid()]
        else:
            return obconn.is_auto_connect()

    def obconn_set_auto_connect(self, obconn, value):
        assert obconn.get_source() in [bnetd.PluginObjectSource.LIB, bnetd.PluginObjectSource.CACHE]
        self._data["obconn"]["auto-connect"][obconn.get_uuid()] = bool(value)

    def obconn_reset_auto_connect(self, obconn):
        self._data["obconn"]["auto-connect"].pop(obconn.get_uuid())
